﻿using System.IO;
using SipSharp.Messages.Headers;

namespace SipSharp
{
    /// <summary>
    /// Common properties for requests and responses.
    /// </summary>
    public interface IMessage
    {
        /// <summary>
        /// Gets body stream.
        /// </summary>
        Stream Body { get; }

        /// <summary>
        /// Gets or sets call id.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The Call-ID header field acts as a unique identifier to group together a series
        /// of messages
        /// </para>
        /// <para>
        /// In a new request created by a UAC outside of any dialog, the Call-ID header
        /// field MUST be selected by the UAC as a globally unique identifier over space
        /// and time unless overridden by method-specific behavior. All SIP UAs must have a
        /// means to guarantee that the Call- ID header fields they produce will not be
        /// inadvertently generated by any other UA. 
        /// <para>
        /// Note that when requests are retried
        /// after certain failure responses that solicit an amendment to a request (for
        /// example, a challenge for authentication), these retried requests are not
        /// considered new requests, and therefore do not need new Call-ID header fields;
        /// see Section 8.1.3.5 (RFC 3261).
        /// </para>
        /// </remarks>
        string CallId { get; set; }

        /// <summary>
        /// Gets number of bytes in body.
        /// </summary>
        int ContentLength { get; set; }

        /// <summary>
        /// Gets or sets transaction identifier.
        /// </summary>
        /// <remarks>
        /// The CSeq header field serves as a way to identify and order transactions. It
        /// consists of a sequence number and a method. The method MUST match that of the
        /// request. For non-REGISTER requests outside of a dialog, the sequence number
        /// value is arbitrary. The sequence number value MUST be expressible as a 32-bit
        /// unsigned integer and MUST be less than 2**31. As long as it follows the above
        /// guidelines, a client may use any mechanism it would like to select CSeq header
        /// field values.
        /// </remarks>
        CSeq CSeq { get; set; }

        /// <summary>
        /// Gets or sets whom the request is from.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The From header field indicates the logical identity of the initiator of the
        /// request, possibly the user's address-of-record. Like the To header field, it
        /// contains a URI and optionally a display name. It is used by SIP elements to
        /// determine which processing rules to apply to a request (for example, automatic
        /// call rejection). As such, it is very important that the From URI not contain IP
        /// addresses or the FQDN of the host on which the UA is running, since these are
        /// not logical names.
        /// </para><para>
        /// The From header field allows for a display name. A UAC SHOULD use the display
        /// name "Anonymous", along with a syntactically correct, but otherwise meaningless
        /// URI (like sip:thisis@anonymous.invalid), if the identity of the client is to
        /// remain hidden.
        /// </para><para>
        /// Usually, the value that populates the From header field in
        /// requests generated by a particular UA is pre-provisioned by the user or by the
        /// administrators of the user's local domain. If a particular UA is used by
        /// multiple users, it might have switchable profiles that include a URI
        /// corresponding to the identity of the profiled user. Recipients of requests can
        /// authenticate the originator of a request in order to ascertain that they are
        /// who their From header field claims they are (see Section 22 for more on
        /// authentication).
        /// </para>
        /// </remarks>
        Contact From { get; set; }

        /// <summary>
        /// All headers.
        /// </summary>
        IKeyValueCollection<string, IHeader> Headers { get; }

        /// <summary>
        /// Gets whether the response is sent over a reliable protocol
        /// </summary>
        /// <remarks>
        /// <para>Reliable means that the tranport guarantees the arrival of the send data.
        /// TCP is reliable, while UDP is not.
        /// </para>
        /// </remarks>
        bool IsReliableProtocol { get; }

        /// <summary>
        /// Gets or sets SIP protocol version.
        /// </summary>
        /// <example>
        /// SIP/2.0
        /// </example>
        string SipVersion { get; set; }


        /// <summary>
        /// Gets or sets whom the request is intended for.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The To header field first and foremost specifies the desired "logical"
        /// recipient of the request, or the address-of-record of the user or resource that
        /// is the target of this request. This may or may not be the ultimate recipient of
        /// the request. The To header field MAY contain a SIP or SIPS URI, but it may also
        /// make use of other URI schemes (the tel URL (RFC 2806 [9]), for example) when
        /// appropriate. All SIP implementations MUST support the SIP URI scheme. Any
        /// implementation that supports TLS MUST support the SIPS URI scheme. The To
        /// header field allows for a display name.
        /// </para>
        /// <para>
        /// A request outside of a dialog MUST NOT contain a To tag; the tag in
        /// the To field of a request identifies the peer of the dialog.  Since
        /// no dialog is established, no tag is present.
        /// </para>
        /// </remarks>
        /// 
        Contact To { get; set; }


        /// <summary>
        /// Gets proxies that the message have to pass through.
        /// </summary>
        /// <remarks>
        /// <para>The Via header field indicates the transport used for the transaction and
        /// identifies the location where the message is to be sent. A Via header field
        /// value is added only after the transport that will be used to reach the next hop
        /// has been selected.</para>
        /// </remarks>
        Via Via { get; }

        /// <summary>
        /// Validate all mandatory headers.
        /// </summary>
        /// <exception cref="BadRequestException">A header is invalid/missing.</exception>
        void Validate();
    }
}